package com.liu.stockmarket.ui.stock.add

import android.util.Log
import androidx.lifecycle.*
import com.liu.stockmarket.model.KlineResult
import com.liu.stockmarket.model.ResponseResult
import com.liu.stockmarket.model.Stock
import com.liu.stockmarket.repository.database.StockRepository
import com.liu.stockmarket.repository.database.TransactionRecordRepository
import com.liu.stockmarket.repository.database.entity.StockEntity
import com.liu.stockmarket.repository.database.entity.TransactionRecordEntity
import com.liu.stockmarket.repository.network.EasyMoneyRepository
import com.liu.stockmarket.ui.search.SearchResultAdapter
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.math.BigDecimal
import java.time.LocalDate
import java.time.LocalDateTime

class StockAddViewModel(
    private val transactionRecordRepository: TransactionRecordRepository,
    private val stockRepository: StockRepository,
    private val easyMoneyRepository: EasyMoneyRepository
) : ViewModel() {


    private val _formState = MutableLiveData<Form>()

    val formState: LiveData<Form> = _formState

    private val _validResult = MutableLiveData<FormValidResult>()

    val validResult: LiveData<FormValidResult> = _validResult


    private val _saveState = MutableLiveData<ResponseResult<Unit>>()
    val responseState: LiveData<ResponseResult<Unit>> = _saveState

    private val _kline = MutableLiveData<List<Map<LocalDate, BigDecimal>>>()
    val kline: LiveData<List<Map<LocalDate, BigDecimal>>> = _kline


    fun doSave() {
        val validForm = validForm()
        if (validForm != null) {
            _validResult.value = validForm!!
            Log.i(TAG, "保存股票交易记录出现错误：${validForm}")
            _saveState.value = ResponseResult.error("输入填写不完整")
            return
        }
        val form = _formState.value!!
        Log.i(TAG, "开始保存:" + formState.value)



        viewModelScope.launch {

            val stocks = stockRepository.queryByStockCode(form.stock!!.code)

            // 不是自选
            val find = stocks.find {
                !it.self
            }

            if (find == null) {
                //计算手续费成本,买入时要算入成本价
                val fee = form.stockHandlingFee ?: BigDecimal.ZERO
                val feePrice = if (fee == BigDecimal.ZERO) BigDecimal.ZERO else {
                    fee.setScale(5) / form.transactionNumber!!.setScale(5)
                }
                // 股票还不存在记录时
                val stockEntity = StockEntity(
                    id = null,
                    code = form.stock!!.code,
                    name = form.stock!!.name,
                    stockType = form.stock!!.stockType,
                    holdingPrice = form.transactionPrice!! + feePrice, //不是在这样算
                    holdingNumber = form.transactionNumber!!,
                    transactionExchange = form.stock!!.transactionExchange,
                    firstTransactionDate = form.transactionDate!!
                )
                form.stock!!.id = stockRepository.save(stockEntity)
            } else {
                // 股票存在记录时

                val holdingPrice = holdingPrice(
                    form.transactionType,
                    find.holdingPrice,
                    find.holdingNumber,
                    form.transactionPrice!!,
                    form.transactionNumber!!,
                    form.stockHandlingFee!!
                )
                val holdingNumber =
                    if (form.transactionType == TransactionRecordEntity.TransactionType.BUY) {
                        find.holdingNumber + form.transactionNumber!!
                    } else {
                        find.holdingNumber - form.transactionNumber!!
                    }

                val stockNewEntity = StockEntity(
                    id = find.id,
                    code = find.code,
                    name = find.name,
                    stockType = find.stockType,
                    transactionExchange = find.transactionExchange,
                    holdingPrice = holdingPrice,
                    holdingNumber = holdingNumber,
                    updateDateTime = LocalDateTime.now(),
                    createDateTime = find.createDateTime,
                    firstTransactionDate = find.firstTransactionDate
                )

                // 更新持有金额和数量
                stockRepository.update(stockNewEntity)
                form.stock!!.id = find.id
            }
            val transactionRecordEntity = TransactionRecordEntity(
                id = null,
                stockId = form.stock!!.id!!,
                transactionType = form.transactionType,
                transactionDate = form.transactionDate!!,
                transactionPrice = form.transactionPrice!!,
                transactionNumber = form.transactionNumber!!,
                handlingFee = form.stockHandlingFee!!,
            )
            transactionRecordRepository.save(transactionRecordEntity)
            _saveState.value = ResponseResult.success()
        }


    }


    /**
     * 清空输入，方便再次输入
     */
    fun clear() {
        val value = _formState.value
        if (value != null) {
            value.transactionDate = null
            value.transactionNumber = null
            value.transactionPrice = null
            value.stockHandlingFee = null
            _formState.value = value!!
        }

    }


    fun formChanged(
        observer: Boolean = true,
        stock: SearchResultAdapter.Item? = null,
        transactionType: TransactionRecordEntity.TransactionType? = null,
        transactionPrice: BigDecimal? = null,
        transactionNumber: BigDecimal? = null,
        stockHandlingFee: BigDecimal? = null,
        transactionDate: LocalDate? = null,
    ) {

        var value = _formState.value

        if (value == null) {
            if (stock == null) {
                throw IllegalArgumentException("股票未设置")
            }
            value = Form(stock = stock)
        }

        transactionType?.let {
            value.transactionType = it
            with(value) {
                this.stockHandlingFee = handlingFee(
                    this.stock!!.stockType,
                    this.transactionType, this.stock!!.transactionExchange, this.transactionPrice,
                    this.transactionNumber ?: BigDecimal.ZERO
                )
            }
        }

        var a = false
        transactionPrice?.let {
            value.transactionPrice = it
            with(value) {
                this.stockHandlingFee = handlingFee(
                    this.stock!!.stockType,
                    this.transactionType, this.stock!!.transactionExchange, this.transactionPrice,
                    this.transactionNumber ?: BigDecimal.ZERO
                )
            }
            a = true

        }
        transactionNumber?.let {
            value.transactionNumber = it
            with(value) {
                this.stockHandlingFee = handlingFee(
                    this.stock!!.stockType,
                    this.transactionType, this.stock!!.transactionExchange, this.transactionPrice,
                    this.transactionNumber ?: BigDecimal.ZERO
                )
            }
            a = true
        }

        stockHandlingFee?.let {
            value.stockHandlingFee = it
        }
        transactionDate?.let {
            value.transactionDate = it
        }

        if (observer || stock != null || a) {
            _formState.value = value!!
        }


    }

    fun holdingPrice(
        transactionType: TransactionRecordEntity.TransactionType,
        holdingPrice: BigDecimal, holdingNumber: BigDecimal,
        transactionPrice: BigDecimal, transactionNumber: BigDecimal, stockHandlingFee: BigDecimal
    ): BigDecimal {
        if (transactionType == TransactionRecordEntity.TransactionType.BUY) {

            val totalBuyMoney = transactionPrice * transactionNumber
            // 考虑清仓后的
            val totalHoldingMoney = if (holdingPrice.setScale(
                    1,
                    BigDecimal.ROUND_CEILING
                ) != BigDecimal.ZERO.setScale(1, BigDecimal.ROUND_CEILING) &&
                holdingNumber.setScale(1) == BigDecimal.ZERO.setScale(1)
            ) {
                holdingPrice
            } else {
                holdingPrice * holdingNumber
            }



            return (totalHoldingMoney + totalBuyMoney + stockHandlingFee) /
                    (holdingNumber + transactionNumber)

        } else {

            // 当时卖出的金额
            val sellMoney = transactionPrice * transactionNumber

            val youMoney = holdingPrice * holdingNumber


            // 清仓
            if (holdingNumber - transactionNumber <= BigDecimal.ZERO) {
                return youMoney - sellMoney + stockHandlingFee
            }

            return (youMoney - sellMoney + stockHandlingFee) / (holdingNumber - transactionNumber)
        }
    }


    fun getKline() {
        val form = _formState.value ?: throw NullPointerException("股票信息为空")
        val c = form.stock!!.code

        var code = when (form.stock!!.transactionExchange) {
            Stock.TransactionExchange.SH -> {
                "1.${c}"
            }
            Stock.TransactionExchange.SZ -> {
                "0.$c"
            }
            else -> throw IllegalArgumentException("不支持的渠道" + form.stock!!.transactionExchange)
        }
        viewModelScope.launch(Dispatchers.IO) {
            val kline = easyMoneyRepository.kline(code, LocalDate.now())
            parse(kline)
        }

    }

    private fun parse(kline: KlineResult?) {
        if (kline == null) {
            return
        } else {
            if (kline.data != null) {
                _kline.postValue(
                    kline.data.klines
                        .map {
                            val temp = it.split(",")
                            mapOf(LocalDate.parse(temp[0]) to BigDecimal(temp[2]))
                        }.toList()
                )
            }
        }


    }

    /**
     *@param stockType 类型：股票、可转债
     * @param transactionType 交易类型
     * @param transactionPrice 交易单价
     * @param transactionNumber 交易数量
     */
    private fun handlingFee(
        stockType: Stock.StockType,
        transactionType: TransactionRecordEntity.TransactionType,
        transactionExchange: Stock.TransactionExchange,
        transactionPrice: BigDecimal?,
        transactionNumber: BigDecimal
    ): BigDecimal? {
        return when (stockType) {
            Stock.StockType.STOCK -> {
                stockHandlingFee(
                    transactionType,
                    transactionExchange,
                    transactionPrice,
                    transactionNumber
                )
            }
            Stock.StockType.BOND -> {
                bondHandlingFee(
                    transactionExchange,
                    transactionPrice,
                    transactionNumber
                )
            }
            else -> {
                BigDecimal.ZERO
            }
        }
    }


    /**
     * 计算股票交易手续费
     *
     * @param transactionType 交易类型 买入、卖出
     * @param transactionExchange 交易所 目前支持 沪A、深A
     * @param transactionPrice 成交价
     * @param transactionNumber 成交数量
     * @return 手续费
     */
    private fun stockHandlingFee(
        transactionType: TransactionRecordEntity.TransactionType,
        transactionExchange: Stock.TransactionExchange,
        transactionPrice: BigDecimal?,
        transactionNumber: BigDecimal
    ): BigDecimal? {

        if (transactionPrice == null || transactionNumber == BigDecimal.ZERO) {
            return null
        }

        if (!(transactionExchange == Stock.TransactionExchange.SZ || transactionExchange == Stock.TransactionExchange.SH)) {
            Log.i(TAG, "只支持沪A或深A的手续费计算")
            return null
        }
        // 股票成交金额
        val totalTransactionMoney = transactionPrice * transactionNumber

        // 佣金费率
        val commissionRate = BigDecimal("0.00025")

        // 佣金
        var commission = totalTransactionMoney * commissionRate

        // 最低收取5元
        commission = if (commission < BigDecimal("5")) BigDecimal("5") else commission

        // 印花税 买入不收
        val stampDuty = if (transactionType == TransactionRecordEntity.TransactionType.SELL) {
            totalTransactionMoney * BigDecimal("0.001")
        } else {
            BigDecimal.ZERO
        }

        // 过户费 深A 不收
        val transferFee = if (transactionExchange == Stock.TransactionExchange.SH) {
            totalTransactionMoney * BigDecimal("0.00002")
        } else {
            BigDecimal.ZERO
        }


        return commission + stampDuty + transferFee
    }

    /**
     * 计算可转债交易手续费
     *
     * @param transactionPrice 成交价
     * @param transactionNumber 成交数量
     * @return 手续费
     */
    private fun bondHandlingFee(
        transactionExchange: Stock.TransactionExchange,
        transactionPrice: BigDecimal?,
        transactionNumber: BigDecimal
    ): BigDecimal? {

        if (transactionPrice == null || transactionNumber == BigDecimal.ZERO) {
            return null
        }

        if (!(transactionExchange == Stock.TransactionExchange.SZ || transactionExchange == Stock.TransactionExchange.SH)) {
            Log.i(TAG, "只支持沪A或深A的手续费计算")
            return null
        }
        // 股票成交金额
        val totalTransactionMoney = transactionPrice * transactionNumber


        return if (transactionExchange == Stock.TransactionExchange.SZ) {
            // 佣金费率
            val commissionRate = BigDecimal("0.001")

            // 佣金
            totalTransactionMoney * commissionRate
        } else {
            // 佣金费率
            val commissionRate = BigDecimal("0.0001")
            val commission = totalTransactionMoney * commissionRate
            if (commission < BigDecimal("1")) BigDecimal("1") else commission
        }

    }


    private fun validForm(): FormValidResult? {
        val value = _formState.value!!
        if (value.transactionPrice == null || value.transactionPrice == BigDecimal.ZERO) {
            return FormValidResult(transactionPrice = "未设置成交价")
        }

        if (value.transactionNumber == null || value.transactionNumber == BigDecimal.ZERO) {
            return FormValidResult(transactionNumber = "未设置成交数量")
        }

        if (value.transactionDate == null) {
            return FormValidResult(transactionDate = "未设置交易时间")
        }
        if (value.stockHandlingFee == null) {
            return FormValidResult(stockHandlingFee = "未设置手续费")
        }

        return null
    }


    companion object {
        private const val TAG = "StockAddViewModel"
    }


    class StockAddViewModelFactory(
        private val transactionRecordRepository: TransactionRecordRepository,
        private val stockRepository: StockRepository,
        private val easyMoneyRepository: EasyMoneyRepository
    ) :
        ViewModelProvider.Factory {
        override fun <T : ViewModel?> create(modelClass: Class<T>): T {
            @Suppress("UNCHECKED_CAST")
            return StockAddViewModel(
                transactionRecordRepository,
                stockRepository,
                easyMoneyRepository
            ) as T
        }

    }
}